package com.questetra.OAuth.core
{
    import com.adobe.serialization.json.JSON;
    
    import flash.net.URLRequest;
    import flash.net.URLVariables;
    
    public class OAuthService
    {
        public function OAuthService(requestTokenUrl:String, authorizeUrl:String, accessTokenUrl:String):void
        {
            _accessTokenUrl = accessTokenUrl;
            _authorizeUrl = authorizeUrl;
            _requestTokenUrl = requestTokenUrl;
            this.oauthManager = new OAuthManager();
        }
        
        private var _accessTokenUrl:String = null;
        private var _authorizeUrl:String = null;
        private var _requestTokenUrl:String = null;
        
        private var _contextPath:String = null;
        public function get contextPath():String
        {
            return _contextPath;
        }
        public function set contextPath(value:String):void
        {
            _contextPath = value;
            setUp();
        }
        
        private var _consumerKey:String = null;
        public function set consumerKey(value:String):void
        {
            _consumerKey = value;
            setUp();
        }
        
        private var _consumerSecret:String = null;
        public function set consumerSecret(value:String):void
        {
            _consumerSecret = value;
            setUp();
        }
        
        private var _oauthCallbackUrl:String = null;
        public function set oauthCallbackUrl(value:String):void
        {
            _oauthCallbackUrl = value;
            setUp();
        }
        
        private var _oauthManager:OAuthManager;
        public function get oauthManager():OAuthManager
        {
            return _oauthManager;
        }
        public function set oauthManager(value:OAuthManager):void
        {
            _oauthManager = value;
            _oauthManager.addEventListener(OAuthEvent.ON_ACCESS_TOKEN_RECEIVED, onAccessTokenReceived, false, 0, true);
            _oauthManager.addEventListener(OAuthEvent.ON_ACCESS_TOKEN_FAILED, onAccessTokenFailed, false, 0, true);
            _oauthManager.addEventListener(OAuthEvent.ON_REQUEST_TOKEN_RECEIVED, onRequestTokenReceived, false, 0, true);
            _oauthManager.addEventListener(OAuthEvent.ON_REQUEST_TOKEN_FAILED, onRequestTokenFailed, false, 0, true);
            _oauthManager.addEventListener(OAuthEvent.ON_REQUEST_COMPLETE, onRequestComplete, false, 0, true);
            setUp();
        }
        
        private function setUp():void
        {
            if (!_consumerKey || !_consumerSecret || !_contextPath)
            {
                trace("no set up...");
                return;
            }
            _oauthManager.consumerKey = _consumerKey;
            _oauthManager.consumerSecret = _consumerSecret;
            _oauthManager.url_oauth_callback = _oauthCallbackUrl;
            _oauthManager.url_access_token = _contextPath + _accessTokenUrl;
            _oauthManager.url_authorize = _contextPath + _authorizeUrl;
            _oauthManager.url_request_token = _contextPath + _requestTokenUrl;
            trace("set up done.");
        }
        
        // ------ 認証関連 ---------------------------------------------------------------------
        
        private var _authorizeCallback:Function;
        private var _authorizeCallbackTarget:Object = null;
        public function authorize(callback:Function, target:Object):void
        {
            _authorizeCallback = callback;
            _authorizeCallbackTarget = target;
            _oauthManager.requestToken();
            return;
        }
        
        private function onRequestTokenReceived(event:OAuthEvent):void
        {
            var request:URLRequest = _oauthManager.requestAuthorization();
            _authorizeCallback.call(_authorizeCallbackTarget, request);
        }
        
        private function onRequestTokenFailed(event:OAuthEvent):void
        {
            _authorizeCallback.call(_authorizeCallbackTarget);
        }
        
        private var _verifierOkCallback:Function = null;
        private var _verifierNgCallback:Function = null;
        private var _verifierTarget:Object = null;
        public function setVerifier(
            verifier:String,
            okCallback:Function=null,
            ngCallback:Function=null,
            verifierTarget:Object=null):void
        {
            _verifierOkCallback = okCallback;
            _verifierNgCallback = ngCallback;
            _verifierTarget = verifierTarget;
            _oauthManager.requestAccessToken(verifier);
        }
        
        private function onAccessTokenReceived(event:OAuthEvent):void
        {
            if (_verifierOkCallback != null)
            {
                _verifierOkCallback.call(_verifierTarget);
            }
        }
        
        private function onAccessTokenFailed(event:OAuthEvent):void
        {
            if (_verifierNgCallback != null)
            {
                _verifierNgCallback.call(_verifierTarget);
            }
        }

        // ------ データ取得 ---------------------------------------------------------------------
        
        private var _requestCallback:Function = null;
        private var _requestTarget:Object = null;
        protected function request(
            method:String,
            url:String,
            variables:URLVariables,
            callback:Function,
            requestTarget:Object):Boolean
        {
            if (!_oauthManager.isAuthorised())
            {
                return false;
            }
            _requestCallback = callback;
            _requestTarget = requestTarget;
            
            _oauthManager.request(method, url, variables);
            
            return true;
        }
        
        private function onRequestComplete(event:OAuthEvent):void
        {
            var jsonObject:Object = JSON.decode(event.data);
            _requestCallback.call(_requestTarget, jsonObject);
        }
    }
}